2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "AIMessageAliasPlugin.h"
18 #import <Adium/AIContentControllerProtocol.h>
19 #import <Adium/AIAccountControllerProtocol.h>
20 #import <AIUtilities/AIAttributedStringAdditions.h>
21 #import <AIUtilities/AIDateFormatterAdditions.h>
22 #import <Adium/AIAccount.h>
23 #import <Adium/AIContentMessage.h>
24 #import <Adium/AIContentObject.h>
25 #import <Adium/AIListContact.h>
27 @interface AIMessageAliasPlugin (PRIVATE)
28 - (NSMutableAttributedString *)replaceKeywordsInString:(NSAttributedString *)original context:(id)context;
31 @implementation AIMessageAliasPlugin
35 //Register us as a filter
36 [[adium contentController] registerContentFilter:self ofType:AIFilterDisplay direction:AIFilterIncoming];
37 [[adium contentController] registerContentFilter:self ofType:AIFilterAutoReplyContent direction:AIFilterOutgoing];
38 [[adium contentController] registerContentFilter:self ofType:AIFilterTooltips direction:AIFilterIncoming];
39 [[adium contentController] registerContentFilter:self ofType:AIFilterContactList direction:AIFilterIncoming];
42 - (void)uninstallPlugin
44 [[adium contentController] unregisterContentFilter:self];
47 - (NSAttributedString *)filterAttributedString:(NSAttributedString *)inAttributedString context:(id)context
49 if (!inAttributedString || ![inAttributedString length]) return inAttributedString;
51 //Filter keywords in the message
52 NSMutableAttributedString *filteredMessage = [self replaceKeywordsInString:inAttributedString context:context];;
54 //Filter keywords in URLs (For AIM subprofile links, mostly)
55 int length = [(filteredMessage ? filteredMessage : inAttributedString) length];
56 NSRange scanRange = NSMakeRange(0, 0);
57 while (NSMaxRange(scanRange) < length) {
58 id linkURL = [(filteredMessage ? filteredMessage : inAttributedString) attribute:NSLinkAttributeName
59 atIndex:NSMaxRange(scanRange)
60 effectiveRange:&scanRange];
62 NSString *linkURLString;
64 if ([linkURL isKindOfClass:[NSURL class]]) {
65 linkURLString = (NSString *)CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault,
66 (CFStringRef)[(NSURL *)linkURL absoluteString],
67 /* characters to leave escaped */ CFSTR(""));
68 [linkURLString autorelease];
71 linkURLString = (NSString *)linkURL;
75 //If we found a URL, replace any keywords within it
76 NSString *result = [[self replaceKeywordsInString:[NSAttributedString stringWithString:linkURLString]
77 context:context] string];
81 NSString *escapedLinkURLString;
82 NSString *charactersToLeaveUnescaped = @"#";
84 if (!filteredMessage) filteredMessage = [[inAttributedString mutableCopy] autorelease];
85 escapedLinkURLString = (NSString *)CFURLCreateStringByAddingPercentEscapes(/* allocator */ kCFAllocatorDefault,
87 (CFStringRef)charactersToLeaveUnescaped,
88 /* legal characters to escape */ NULL,
89 kCFStringEncodingUTF8);
90 newURL = [NSURL URLWithString:escapedLinkURLString];
93 [filteredMessage addAttribute:NSLinkAttributeName
97 [escapedLinkURLString release];
103 return (filteredMessage ? filteredMessage : inAttributedString);
106 - (float)filterPriority
108 return DEFAULT_FILTER_PRIORITY;
111 //Replace any keywords in the passed string
112 //Returns a mutable version of the passed string if keywords have been replaced. Otherwise returns
113 - (NSMutableAttributedString *)replaceKeywordsInString:(NSAttributedString *)attributedString context:(id)context
115 NSString *str = [attributedString string];
116 NSMutableAttributedString *newAttributedString = nil;
119 //If we're passed content, our account will be the destination of that content
120 //If we're passed a list object, we can use the name of the preferred account for that object
121 if ([str rangeOfString:@"%n"].location != NSNotFound) {
122 NSString *replacement = nil;
124 if ([context isKindOfClass:[AIContentObject class]]) {
125 replacement = [[context destination] UID]; //This exists primarily for AIM compatibility; AIM uses the UID (no formatting).
126 } else if ([context isKindOfClass:[AIListContact class]]) {
127 replacement = [[[adium accountController] preferredAccountForSendingContentType:CONTENT_MESSAGE_TYPE
128 toContact:context] formattedUID];
132 if (!newAttributedString) newAttributedString = [[attributedString mutableCopy] autorelease];
134 [newAttributedString replaceOccurrencesOfString:@"%n"
135 withString:replacement
136 options:NSLiteralSearch
137 range:NSMakeRange(0, [newAttributedString length])];
142 if ([str rangeOfString:@"%d"].location != NSNotFound) {
143 NSCalendarDate *currentDate = [NSCalendarDate calendarDate];
144 NSString *calendarFormat = [[NSUserDefaults standardUserDefaults] objectForKey:NSShortDateFormatString];
146 if (!newAttributedString) newAttributedString = [[attributedString mutableCopy] autorelease];
148 [newAttributedString replaceOccurrencesOfString:@"%d"
149 withString:[currentDate descriptionWithCalendarFormat:calendarFormat]
150 options:NSLiteralSearch
151 range:NSMakeRange(0, [newAttributedString length])];
155 if ([str rangeOfString:@"%t"].location != NSNotFound) {
156 NSCalendarDate *currentDate = [NSCalendarDate calendarDate];
157 NSString *localDateFormat = [NSDateFormatter localizedDateFormatStringShowingSeconds:YES
160 if (!newAttributedString) newAttributedString = [[attributedString mutableCopy] autorelease];
162 [newAttributedString replaceOccurrencesOfString:@"%t"
163 withString:[currentDate descriptionWithCalendarFormat:localDateFormat]
164 options:NSLiteralSearch
165 range:NSMakeRange(0, [newAttributedString length])];
168 return newAttributedString;